{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import argparse"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "parser = argparse.ArgumentParser(description=\"Generate Surrounding Camera Bird Eye View\")\n",
    "parser.add_argument('-fw', '--FRAME_WIDTH', default=1280, type=int, help='Camera Frame Width')\n",
    "parser.add_argument('-fh', '--FRAME_HEIGHT', default=1024, type=int, help='Camera Frame Height')\n",
    "parser.add_argument('-bw', '--BEV_WIDTH', default=1000, type=int, help='BEV Frame Width')\n",
    "parser.add_argument('-bh', '--BEV_HEIGHT', default=1000, type=int, help='BEV Frame Height')\n",
    "parser.add_argument('-cw', '--CAR_WIDTH', default=250, type=int, help='Car Frame Width')\n",
    "parser.add_argument('-ch', '--CAR_HEIGHT', default=400, type=int, help='Car Frame Height')\n",
    "parser.add_argument('-fs', '--FOCAL_SCALE', default=1, type=float, help='Camera Undistort Focal Scale')\n",
    "parser.add_argument('-ss', '--SIZE_SCALE', default=2, type=float, help='Camera Undistort Size Scale')\n",
    "parser.add_argument('-blend','--BLEND_FLAG', default=False, type=bool, help='Blend BEV Image (Ture/False)')\n",
    "parser.add_argument('-balance','--BALANCE_FLAG', default=False, type=bool, help='Balance BEV Image (Ture/False)')\n",
    "args = parser.parse_args([])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# args.FRAME_WIDTH = 1280     # 相机原始图像宽度\n",
    "# args.FRAME_HEIGHT = 1024    # 相机原始图像高度\n",
    "# args.BEV_WIDTH = 1000       # 最终鸟瞰拼接图宽度\n",
    "# args.BEV_HEIGHT = 1000      # 最终鸟瞰拼接图高度\n",
    "# args.CAR_WIDTH = 250        # 鸟瞰图中间车辆宽度（与car图片相对应）\n",
    "# args.CAR_HEIGHT = 400       # 鸟瞰图中间车辆高度（与car图片相对应）\n",
    "# args.FOCAL_SCALE = 1        # 去畸变时相机焦距缩放系数（与内外惨标定时一致）\n",
    "# args.SIZE_SCALE = 2         # 去畸变时相机尺寸缩放系数（与内外惨标定时一致）\n",
    "# args.BLEND_FLAG = True      # 鸟瞰图拼接是否采用图像融合\n",
    "# args.BALANCE_FLAG = True    # 鸟瞰图拼接是否采用图像平衡"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 直接赋值避免频繁读取args\n",
    "FRAME_WIDTH = args.FRAME_WIDTH\n",
    "FRAME_HEIGHT = args.FRAME_HEIGHT\n",
    "BEV_WIDTH = args.BEV_WIDTH\n",
    "BEV_HEIGHT = args.BEV_HEIGHT\n",
    "CAR_WIDTH = args.CAR_WIDTH\n",
    "CAR_HEIGHT = args.CAR_HEIGHT\n",
    "FOCAL_SCALE = args.FOCAL_SCALE\n",
    "SIZE_SCALE = args.SIZE_SCALE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 图像补充黑边\n",
    "def padding(img,width,height):\n",
    "    H = img.shape[0]\n",
    "    W = img.shape[1]\n",
    "    top = (height - H) // 2 \n",
    "    bottom = (height - H) // 2 \n",
    "    if top + bottom + H < height:\n",
    "        bottom += 1\n",
    "    left = (width - W) // 2 \n",
    "    right = (width - W) // 2 \n",
    "    if left + right + W < width:\n",
    "        right += 1\n",
    "    img = cv2.copyMakeBorder(img, top, bottom, left, right,\n",
    "                             cv2.BORDER_CONSTANT, value = (0,0,0)) \n",
    "    return img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "code_folding": []
   },
   "outputs": [],
   "source": [
    "# 色彩平衡（白平衡）\n",
    "def color_balance(image):\n",
    "    b, g, r = cv2.split(image)\n",
    "    B = np.mean(b)\n",
    "    G = np.mean(g)\n",
    "    R = np.mean(r)\n",
    "    K = (R + G + B) / 3\n",
    "    Kb = K / B\n",
    "    Kg = K / G\n",
    "    Kr = K / R\n",
    "    cv2.addWeighted(b, Kb, 0, 0, 0, b)\n",
    "    cv2.addWeighted(g, Kg, 0, 0, 0, g)\n",
    "    cv2.addWeighted(r, Kr, 0, 0, 0, r)\n",
    "    return cv2.merge([b,g,r])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 亮度平衡 根据输入的四张图像进行计算平均亮度 转化为HSV通道\n",
    "def luminance_balance(images):\n",
    "    [front,back,left,right] = [cv2.cvtColor(image,cv2.COLOR_BGR2HSV) \n",
    "                               for image in images]\n",
    "    hf, sf, vf = cv2.split(front)\n",
    "    hb, sb, vb = cv2.split(back)\n",
    "    hl, sl, vl = cv2.split(left)\n",
    "    hr, sr, vr = cv2.split(right)\n",
    "    V_f = np.mean(vf)\n",
    "    V_b = np.mean(vb)\n",
    "    V_l = np.mean(vl)\n",
    "    V_r = np.mean(vr)\n",
    "    V_mean = (V_f + V_b + V_l +V_r) / 4\n",
    "    vf = cv2.add(vf,(V_mean - V_f))\n",
    "    vb = cv2.add(vb,(V_mean - V_b))\n",
    "    vl = cv2.add(vl,(V_mean - V_l))\n",
    "    vr = cv2.add(vr,(V_mean - V_r))\n",
    "    front = cv2.merge([hf,sf,vf])\n",
    "    back = cv2.merge([hb,sb,vb])\n",
    "    left = cv2.merge([hl,sl,vl])\n",
    "    right = cv2.merge([hr,sr,vr])\n",
    "    images = [front,back,left,right]\n",
    "    images = [cv2.cvtColor(image,cv2.COLOR_HSV2BGR) for image in images]\n",
    "    return images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Camera:                   # 相机类 读取参数、去畸变和单应性变换\n",
    "    def __init__(self, name):\n",
    "        # 读取内参、畸变向量、外参的npy文件\n",
    "        self.camera_mat = np.load('./data/{}/camera_{}_K.npy'.format(name,name))\n",
    "        self.dist_coeff = np.load('./data/{}/camera_{}_D.npy'.format(name,name))\n",
    "        self.homography = np.load('./data/{}/camera_{}_H.npy'.format(name,name))\n",
    "        self.camera_mat_dst = self.get_camera_mat_dst()\n",
    "        self.undistort_maps = self.get_undistort_maps()\n",
    "        self.bev_maps = self.get_bev_maps()\n",
    "    \n",
    "    # 获取去畸变的新的相机内参矩阵 可以修改焦距和画幅\n",
    "    def get_camera_mat_dst(self):\n",
    "        camera_mat_dst = self.camera_mat.copy()\n",
    "        camera_mat_dst[0][0] *= FOCAL_SCALE\n",
    "        camera_mat_dst[1][1] *= FOCAL_SCALE\n",
    "        camera_mat_dst[0][2] = FRAME_WIDTH / 2 * SIZE_SCALE\n",
    "        camera_mat_dst[1][2] = FRAME_HEIGHT / 2 * SIZE_SCALE\n",
    "        return camera_mat_dst\n",
    "    \n",
    "    # 获取去畸变映射矩阵\n",
    "    def get_undistort_maps(self):\n",
    "        undistort_maps = cv2.fisheye.initUndistortRectifyMap(\n",
    "                    self.camera_mat, self.dist_coeff, \n",
    "                    np.eye(3, 3), self.camera_mat_dst,\n",
    "                    (int(FRAME_WIDTH * SIZE_SCALE), int(FRAME_HEIGHT * SIZE_SCALE)), cv2.CV_16SC2)\n",
    "        return undistort_maps\n",
    "    \n",
    "    # 对去畸变映射矩阵进行单应性变换\n",
    "    def get_bev_maps(self):\n",
    "        map1 = self.warp_homography(self.undistort_maps[0])\n",
    "        map2 = self.warp_homography(self.undistort_maps[1])\n",
    "        return (map1, map2)\n",
    "    \n",
    "    # 原始图像去畸变\n",
    "    def undistort(self, img):\n",
    "        return cv2.remap(img, *self.undistort_maps, interpolation = cv2.INTER_LINEAR)\n",
    "        \n",
    "    # 直接对图像进行单应性变换    \n",
    "    def warp_homography(self, img):\n",
    "        return cv2.warpPerspective(img, self.homography, (BEV_WIDTH,BEV_HEIGHT))\n",
    "    \n",
    "    # 利用单应性变换后的映射矩阵进行remap变换，速度更快\n",
    "    def raw2bev(self, img):\n",
    "        return cv2.remap(img, *self.bev_maps, interpolation = cv2.INTER_LINEAR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Mask:                     # 直接拼接四个图像的mask\n",
    "    def __init__(self, name):\n",
    "        self.mask = self.get_mask(name)\n",
    "    \n",
    "    # 预设好的前后左右四个mask的坐标点\n",
    "    def get_points(self, name):\n",
    "        if name == 'front':\n",
    "            points = np.array([\n",
    "                [0, 0],\n",
    "                [BEV_WIDTH, 0], \n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2]\n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'back':\n",
    "            points = np.array([\n",
    "                [0, BEV_HEIGHT],\n",
    "                [BEV_WIDTH, BEV_HEIGHT],\n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2], \n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2]\n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'left':\n",
    "            points = np.array([\n",
    "                [0, 0],\n",
    "                [0, BEV_HEIGHT], \n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2],\n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2]\n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'right':\n",
    "            points = np.array([\n",
    "                [BEV_WIDTH, 0],\n",
    "                [BEV_WIDTH, BEV_HEIGHT], \n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2], \n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2]\n",
    "            ]).astype(np.int32)\n",
    "        else:\n",
    "            raise Exception(\"name should be front/back/left/right\")\n",
    "        return points\n",
    "    \n",
    "    # 填充得到各个mask\n",
    "    def get_mask(self, name):\n",
    "        mask = np.zeros((BEV_HEIGHT,BEV_WIDTH), dtype=np.uint8)\n",
    "        points = self.get_points(name)\n",
    "        return cv2.fillPoly(mask, [points], 255)\n",
    "    \n",
    "    # 位与计算得到mask后的图像\n",
    "    def __call__(self, img):\n",
    "        return cv2.bitwise_and(img, img, mask=self.mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class BlendMask:                # 融合拼接四个图像的mask\n",
    "    def __init__(self,name):\n",
    "        mf = self.get_mask('front')\n",
    "        mb = self.get_mask('back')\n",
    "        ml = self.get_mask('left')\n",
    "        mr = self.get_mask('right')\n",
    "        self.get_lines()\n",
    "        if name == 'front':\n",
    "            mf = self.get_blend_mask(mf, ml, self.lineFL, self.lineLF)\n",
    "            mf = self.get_blend_mask(mf, mr, self.lineFR, self.lineRF)\n",
    "            self.mask = mf\n",
    "        if name == 'back':\n",
    "            mb = self.get_blend_mask(mb, ml, self.lineBL, self.lineLB)\n",
    "            mb = self.get_blend_mask(mb, mr, self.lineBR, self.lineRB)\n",
    "            self.mask = mb\n",
    "        if name == 'left':\n",
    "            ml = self.get_blend_mask(ml, mf, self.lineLF, self.lineFL)\n",
    "            ml = self.get_blend_mask(ml, mb, self.lineLB, self.lineBL)\n",
    "            self.mask = ml\n",
    "        if name == 'right':\n",
    "            mr = self.get_blend_mask(mr, mf, self.lineRF, self.lineFR)\n",
    "            mr = self.get_blend_mask(mr, mb, self.lineRB, self.lineBR)\n",
    "            self.mask = mr\n",
    "        self.weight = np.repeat(self.mask[:, :, np.newaxis], 3, axis=2) / 255.0\n",
    "        self.weight = self.weight.astype(np.float32)\n",
    "    \n",
    "    # 预设好的前后左右四个mask的坐标点，相比直接拼接的mask，有重叠部分，修改数值可以改变重叠范围\n",
    "    def get_points(self, name):\n",
    "        if name == 'front':\n",
    "            points = np.array([\n",
    "                [0, 0],\n",
    "                [BEV_WIDTH, 0], \n",
    "                [BEV_WIDTH, BEV_HEIGHT/5], \n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                [0, BEV_HEIGHT/5], \n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'back':\n",
    "            points = np.array([\n",
    "                [0, BEV_HEIGHT],\n",
    "                [BEV_WIDTH, BEV_HEIGHT],\n",
    "                [BEV_WIDTH, BEV_HEIGHT - BEV_HEIGHT/5],\n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2], \n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2],\n",
    "                [0, BEV_HEIGHT - BEV_HEIGHT/5],\n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'left':\n",
    "            points = np.array([\n",
    "                [0, 0],\n",
    "                [0, BEV_HEIGHT], \n",
    "                [BEV_WIDTH/5, BEV_HEIGHT], \n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2],\n",
    "                [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                [BEV_WIDTH/5, 0]\n",
    "            ]).astype(np.int32)\n",
    "        elif name == 'right':\n",
    "            points = np.array([\n",
    "                [BEV_WIDTH, 0],\n",
    "                [BEV_WIDTH, BEV_HEIGHT], \n",
    "                [BEV_WIDTH - BEV_WIDTH/5, BEV_HEIGHT],\n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2], \n",
    "                [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                [BEV_WIDTH - BEV_WIDTH/5, 0]\n",
    "            ]).astype(np.int32)\n",
    "        else:\n",
    "            raise Exception(\"name should be front/back/left/right\")\n",
    "        return points\n",
    "    \n",
    "    # 填充得到各个mask\n",
    "    def get_mask(self, name):\n",
    "        mask = np.zeros((BEV_HEIGHT,BEV_WIDTH), dtype=np.uint8)\n",
    "        points = self.get_points(name)\n",
    "        return cv2.fillPoly(mask, [points], 255)\n",
    "    \n",
    "    # 得到预设的mask重叠部分的各个线段\n",
    "    def get_lines(self):\n",
    "        self.lineFL = np.array([\n",
    "                        [0, BEV_HEIGHT/5], \n",
    "                        [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineFR = np.array([\n",
    "                        [BEV_WIDTH, BEV_HEIGHT/5], \n",
    "                        [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2],\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineBL = np.array([\n",
    "                        [0, BEV_HEIGHT - BEV_HEIGHT/5], \n",
    "                        [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2],\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineBR = np.array([\n",
    "                        [BEV_WIDTH, BEV_HEIGHT - BEV_HEIGHT/5], \n",
    "                        [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2],\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineLF = np.array([\n",
    "                        [BEV_WIDTH/5, 0],\n",
    "                        [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2]\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineLB = np.array([\n",
    "                        [BEV_WIDTH/5, BEV_HEIGHT],\n",
    "                        [(BEV_WIDTH-CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2]\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineRF = np.array([\n",
    "                        [BEV_WIDTH - BEV_WIDTH/5, 0],\n",
    "                        [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT-CAR_HEIGHT)/2]\n",
    "                    ]).astype(np.int32)\n",
    "        self.lineRB = np.array([\n",
    "                        [BEV_WIDTH - BEV_WIDTH/5, BEV_HEIGHT],\n",
    "                        [(BEV_WIDTH+CAR_WIDTH)/2, (BEV_HEIGHT+CAR_HEIGHT)/2]\n",
    "                    ]).astype(np.int32)\n",
    "        \n",
    "    # 根据重叠部分的点到上述线段的距离，得到该处的权重值\n",
    "    def get_blend_mask(self, maskA, maskB, lineA, lineB):\n",
    "        overlap = cv2.bitwise_and(maskA, maskB)           # 重叠区域\n",
    "        indices = np.where(overlap != 0)                  # 重叠区域的坐标索引\n",
    "        for y, x in zip(*indices):\n",
    "            distA = cv2.pointPolygonTest(np.array(lineA), (x, y), True)     # 到重叠区域边缘的距离A\n",
    "            distB = cv2.pointPolygonTest(np.array(lineB), (x, y), True)     # 到重叠区域边缘的距离B\n",
    "            maskA[y, x] = distA**2 / (distA**2 + distB**2 + 1e-6) * 255     # 根据距离的平方比值确定该处权重\n",
    "        return maskA\n",
    "    \n",
    "    # 将图像乘以权重mask\n",
    "    def __call__(self, img):\n",
    "        return (img * self.weight).astype(np.uint8)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class BevGenerator:                   # 环视鸟瞰图生成器\n",
    "    def __init__(self, blend=args.BLEND_FLAG, balance=args.BALANCE_FLAG):\n",
    "        self.init_args()\n",
    "        self.cameras = [Camera('front'), Camera('back'), \n",
    "                        Camera('left'), Camera('right')]\n",
    "        self.blend = blend\n",
    "        self.balance = balance\n",
    "        if not self.blend:\n",
    "            self.masks = [Mask('front'), Mask('back'), \n",
    "                          Mask('left'), Mask('right')]\n",
    "        else:\n",
    "            self.masks = [BlendMask('front'), BlendMask('back'), \n",
    "                      BlendMask('left'), BlendMask('right')]\n",
    "    \n",
    "    # 获取args参数，供外部调用修改参数\n",
    "    @staticmethod\n",
    "    def get_args():\n",
    "        return args\n",
    "        \n",
    "    # 重新赋值args参数\n",
    "    def init_args(self):\n",
    "        global FRAME_WIDTH, FRAME_HEIGHT, BEV_WIDTH, BEV_HEIGHT\n",
    "        global CAR_WIDTH, CAR_HEIGHT, FOCAL_SCALE, SIZE_SCALE\n",
    "        FRAME_WIDTH = args.FRAME_WIDTH\n",
    "        FRAME_HEIGHT = args.FRAME_HEIGHT\n",
    "        BEV_WIDTH = args.BEV_WIDTH\n",
    "        BEV_HEIGHT = args.BEV_HEIGHT\n",
    "        CAR_WIDTH = args.CAR_WIDTH\n",
    "        CAR_HEIGHT = args.CAR_HEIGHT\n",
    "        FOCAL_SCALE = args.FOCAL_SCALE\n",
    "        SIZE_SCALE = args.SIZE_SCALE\n",
    "    \n",
    "    # 输入前后左右四张原始相机图像，生成鸟瞰图，car图像可以不输入\n",
    "    def __call__(self, front, back, left, right, car = None):\n",
    "        images = [front,back,left,right]\n",
    "        if self.balance:\n",
    "            images = luminance_balance(images)        # 亮度平衡\n",
    "        images = [mask(camera.raw2bev(img)) \n",
    "                  for img, mask, camera in zip(images, self.masks, self.cameras)]   # 鸟瞰变换并加上mask\n",
    "        surround = cv2.add(images[0],images[1])\n",
    "        surround = cv2.add(surround,images[2])\n",
    "        surround = cv2.add(surround,images[3])        # 将所有图像拼接起来\n",
    "        if self.balance:\n",
    "            surround = color_balance(surround)        # 白平衡\n",
    "        if car is not None:\n",
    "            surround = cv2.add(surround,car)          # 加上车辆图片\n",
    "        return surround"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def main():\n",
    "    front = cv2.imread('./data/front/front.jpg')      # 前相机图片\n",
    "    back = cv2.imread('./data/back/back.jpg')         # 后相机图片\n",
    "    left = cv2.imread('./data/left/left.jpg')         # 左相机图片\n",
    "    right = cv2.imread('./data/right/right.jpg')      # 右相机图片\n",
    "    car = cv2.imread('./data/car.jpg')                # 车辆图片\n",
    "    car = padding(car, BEV_WIDTH, BEV_HEIGHT)         # 将车辆图片补充黑边至鸟瞰图大小\n",
    "    \n",
    "    bev = BevGenerator(blend=True,balance=True)       # 初始化环视鸟瞰图生成器\n",
    "    surround = bev(front,back,left,right,car)         # 得到环视鸟瞰图\n",
    "    \n",
    "    cv2.namedWindow('surround', flags = cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)\n",
    "    cv2.imshow('surround', surround)\n",
    "    cv2.imwrite('./surround.jpg', surround)\n",
    "    cv2.waitKey(0)\n",
    "    cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
